package com.zzyl.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.collection.CollectionUtil;
import com.aliyun.iot20180120.Client;
import com.aliyun.iot20180120.models.*;
import com.google.common.collect.Lists;
import com.zzyl.base.PageResponse;
import com.zzyl.base.ResponseResult;
import com.zzyl.dto.DeviceDto;
import com.zzyl.entity.Device;
import com.zzyl.exception.BaseException;
import com.zzyl.mapper.DeviceMapper;
import com.zzyl.properties.AliIoTConfigProperties;
import com.zzyl.service.DeviceService;
import com.zzyl.utils.ObjectUtil;
import com.zzyl.vo.DeviceVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author sjqn
 * @date 2023/11/13
 */
@Service
public class DeviceServiceImpl implements DeviceService {

    @Autowired
    private Client client;

    @Autowired
    private AliIoTConfigProperties aliIoTConfigProperties;

    @Autowired
    private DeviceMapper deviceMapper;

    /**
     * 注册设备
     *
     * @param deviceDto
     * @return
     */
    @Override
    public ResponseResult registerDevice(DeviceDto deviceDto) throws Exception {
        //iot中新增设备
        RegisterDeviceRequest registerDeviceRequest = deviceDto.getRegisterDeviceRequest();
        registerDeviceRequest.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        RegisterDeviceResponse response = client.registerDevice(registerDeviceRequest);
        if (response.getBody().getSuccess()) {

            //属性拷贝
            Device device = BeanUtil.toBean(deviceDto, Device.class);
            //设备id
            device.setDeviceId(response.getBody().getData().getIotId());
            device.setDeviceName(response.getBody().getData().deviceName);
            device.setNoteName(response.getBody().getData().getNickname());//设备昵称

            //到iot中查询产品名称
            QueryProductRequest queryProductRequest = new QueryProductRequest();
            queryProductRequest.setProductKey(deviceDto.getProductKey());
            queryProductRequest.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
            QueryProductResponse queryProductResponse = client.queryProduct(queryProductRequest);
            device.setProductName(queryProductResponse.getBody().getData().productName);

            device.setProductId(queryProductResponse.getBody().getData().productKey);//设备昵称

            if (device.getLocationType() == 0) {
                device.setPhysicalLocationType(-1);
            }

            try {
                //在数据库中新增设备
                deviceMapper.insert(device);
            } catch (Exception e) {

                //删除设备（iot）
                DeleteDeviceRequest deleteDeviceRequest = new DeleteDeviceRequest();
                deleteDeviceRequest.setIotId(device.getDeviceId());
                deleteDeviceRequest.setDeviceName(device.getDeviceName());
                deleteDeviceRequest.setProductKey(deviceDto.productKey);
                deleteDeviceRequest.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
                client.deleteDevice(deleteDeviceRequest);

                throw new BaseException("该老人/位置已绑定该产品，请重新选择");
            }
            return ResponseResult.success();
        }

        throw new BaseException(response.getBody().getErrorMessage());
    }

    /**
     * 按照产品key查询设备列表
     *
     * @param request
     * @return
     */
    @Override
    public ResponseResult<PageResponse<DeviceVo>> queryDevice(QueryDeviceRequest request) throws Exception {
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        QueryDeviceResponse response = client.queryDevice(request);
        QueryDeviceResponseBody body = response.getBody();
        if (body.getSuccess() && ObjectUtil.isNotEmpty(body.getData())) {
            //取出设备id集合
            List<QueryDeviceResponseBody.QueryDeviceResponseBodyDataDeviceInfo> deviceInfo = body.getData().getDeviceInfo();
            List<String> idList = deviceInfo.stream()
                    .map(QueryDeviceResponseBody.QueryDeviceResponseBodyDataDeviceInfo::getIotId).collect(Collectors.toList());
            //数据库中的设备数据
            List<DeviceVo> deviceVoList = deviceMapper.selectByDeviceIds(idList);

            //转换为一个map：{iotid:设备对象}
            Map<String, DeviceVo> collect = deviceVoList.stream().collect(Collectors.toMap(DeviceVo::getDeviceId, t -> t));

            List<DeviceVo> deviceVos = new ArrayList<>();

            //整合数据
            deviceInfo.forEach(x -> {
                if (ObjectUtil.isNotEmpty(collect.get(x.getIotId()))) {
                    DeviceVo deviceVo = collect.get(x.getIotId());
                    BeanUtil.copyProperties(x, deviceVo);
                    deviceVos.add(deviceVo);
                }
            });

            //分页对象
            PageResponse<DeviceVo> pageResponse = PageResponse.of(deviceVos, request.getCurrentPage(), request.getPageSize(), (long) body.getPageCount(), (long) body.getTotal());
            return ResponseResult.success(pageResponse);
        }

        return ResponseResult.success();
    }

    /**
     * 查询设备详细数据
     *
     * @param request
     * @return
     */
    @Override
    public ResponseResult queryDeviceDetail(QueryDeviceDetailRequest request) throws Exception {

        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        QueryDeviceDetailResponse response = client.queryDeviceDetail(request);
        if (response.getBody().getSuccess()) {
            //再去查询数据库
            List<DeviceVo> deviceVos = deviceMapper.selectByDeviceIds(Arrays.asList(response.getBody().getData().getIotId()));
            if (CollectionUtil.isNotEmpty(deviceVos)) {
                DeviceVo deviceVo = deviceVos.get(0);
                QueryDeviceDetailResponseBody.QueryDeviceDetailResponseBodyData data = response.getBody().getData();
                BeanUtil.copyProperties(data, deviceVo, CopyOptions.create().ignoreNullValue());
                return ResponseResult.success(deviceVo);
            }
        }

        return ResponseResult.success();
    }

    /**
     * 更新设备
     *
     * @param deviceDto
     * @throws Exception
     */
    @Override
    public void updateDevice(DeviceDto deviceDto) throws Exception {
        BatchUpdateDeviceNicknameRequest request = new BatchUpdateDeviceNicknameRequest();
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        BatchUpdateDeviceNicknameRequest.BatchUpdateDeviceNicknameRequestDeviceNicknameInfo nicknameInfo = BeanUtil.toBean(deviceDto, BatchUpdateDeviceNicknameRequest.BatchUpdateDeviceNicknameRequestDeviceNicknameInfo.class);
        request.setDeviceNicknameInfo(Lists.newArrayList(nicknameInfo));
        BatchUpdateDeviceNicknameResponse response = client.batchUpdateDeviceNickname(request);
        // 保存位置
        if (Boolean.TRUE.equals(response.getBody().getSuccess())) {
            // 保存位置
            Device device = BeanUtil.toBean(deviceDto, Device.class);
            device.setProductId(deviceDto.getProductKey());
            device.setNoteName(deviceDto.getNickname());
            Device device1 = deviceMapper.selectByPrimaryKey(device.getId());
            if (ObjectUtil.isEmpty(device1)) {
                device.setDeviceId(deviceDto.getIotId());
                device.setNoteName(deviceDto.getNickname());
                device.setProductId(deviceDto.getProductKey());
                device.setDeviceId(deviceDto.getIotId());
                deviceMapper.insert(device);
                return;
            }
            try {
                deviceMapper.updateByPrimaryKeySelective(device);
            } catch (Exception e) {
                throw new BaseException("该老人/位置已绑定该产品，请重新选择");
            }
            return;
        }
        throw new BaseException(response.getBody().getErrorMessage());
    }

    /**
     * 删除设备
     *
     * @param request
     * @throws Exception
     */
    @Override
    public void deleteDevice(DeleteDeviceRequest request) throws Exception {
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        DeleteDeviceResponse response = client.deleteDevice(request);
        if (Boolean.TRUE.equals(response.getBody().getSuccess())) {
            deviceMapper.deleteByDeviceId(request.getIotId());
            return;
        }
        throw new BaseException(response.getBody().getErrorMessage());
    }
}
